#include <iostream>
#include <string>
using namespace std;

/**
 * @author redfrogotr
 * @date 2022-04-24
 */
template <class T>
class Stack
{
private:
    int max;    // stack max capacity
    T *element;
    int top;    // index of the top element of stack

public:
    // size must > 0
    Stack(int size) {
        this->max = size;
        this->element = new T[size];
        this->top = -1;
    }

    ~Stack() {
        if (element) {
            delete []element;
        }
    }

    void push(T x) {
        if (full()) {
            cout << "\n<<ERROR: stack is FULL, push element failed.>>\n";
        } else {
            element[++top] = x;
        }
    }

    T pop() {
        if (empty()) {
            cout << "\n<<ERROR: stack is EMPTY, pop failed. A random element will be returned.>>\n";
            return element[0];
        } 
        // else
        return element[top--];
    }

    bool empty() {
        return top < 0;
    }

    bool full() {
        return top >= max - 1;
    }
};

int main(int argc, char const *argv[])
{
    int size = 3;
    Stack<int> intStack(size);
    Stack<string> strStack(size);

    for (int i = 0; i < size + 1; i++) {
        intStack.push(i);
    }
    for (int i = 0; i < size + 1; i++) {
        cout << intStack.pop() << ' ';
    }
    cout << endl;

    string s("str_");
    for (int i = 0; i < size + 1; i++) {
        char c = 'a' + i;
        strStack.push(s + c);
    }
    for (int i = 0; i < size + 1; i++) {
        cout << strStack.pop() << ' ';
    }
    cout << endl;

    return 0;
}
